// =============================================================
// CSpace test
// ---------------------------------------
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Sep. 4, 2007
// =============================================================
#include <iostream>
#include <sys/timeb.h>
#include <time.h>

#include "CSpace.h"
#include "CMessage.h"
#include "CKeyValue.h"

string &execShell(string &command)
{
        char buf[1024];
        memset((char *)buf, '\0', sizeof(buf));

        FILE *p = popen(command.c_str(), "r");
        if(!p) {
                cout << "pipe open error : " << command << endl;
        }

        // to contain the result of the command execution
        string tmp = "";
        while(fgets(buf, sizeof(buf)-1, p)!=0) {
                tmp += buf;
                memset((char *)buf, '\0', sizeof(buf));
        }

        pclose(p);

        string result;
        int len = tmp.length();
        if(tmp[len-1]=='\n') result = tmp.substr(0,tmp.length()-1);
        else result = tmp;

        command = result;

        return command;
}

int getRandom()
{
	struct timeb itb;
        struct tm *lt;
        ftime(&itb);
        lt = localtime(&itb.time);
        srand(lt->tm_sec+itb.millitm);

        int random_port = rand();

        return random_port;
}

int main(int argc, char **argv)
{
	if(argc<2) {
		cout << "Usages : " << argv[0] << " -r(ead) , -t(ake) , -b(bulk write/take)" << endl;
		exit(-1);
	}

	CSpace space("memory leak test");
	CMessage msg;
	CMessage *res = NULL;


	string cmd_res = "ps -ef";
	cmd_res = execShell(cmd_res);

	msg.set((char *)cmd_res.c_str());



	// read test
	if(strcmp(argv[1],"-r")==0) {
		cout << "[write]current size = " << space.write(&msg) << endl;
		for(long i=0;;i++) {
			res = static_cast<CMessage *>(space.read(res));

			//cout << (char *)res->data << endl;
			delete res;

			if(i>=1000) {
				string mem_status = "free";
				mem_status = execShell(mem_status);
				cout << "[read]current size = " << space.size() << endl;
				cout << mem_status << endl << endl;

				i = -1;
				sleep(3);
			}
		}
	}

	// write and take test
	else if(strcmp(argv[1],"-t")==0) {
		// write and take test
		for(long i=0;;i++) {
			cout << "[write]current size = " << space.write(&msg) << endl;
			res = static_cast<CMessage *>(space.take(res));
			cout << "[take]current size = " << space.size() << endl;

			//cout << (char *)res->data << endl;
			delete res;

			if(i>=1000) {
				string mem_status = "free";
				mem_status = execShell(mem_status);
				cout << mem_status << endl << endl;

				i = -1;
				sleep(3);
			}
		}
	}

	// bulk write and bulk take test
	else if(strcmp(argv[1],"-b")==0) {
		char mon[256];
		sprintf(mon,"cat /proc/%d/status", getpid());
		string mem_status = mon;

		cout << "start mem status : " << endl;
		cout << "==================================================" << endl;
		cout << mon << endl;
		system(mon);
		cout << "==================================================" << endl;
		cout << endl << endl;

		// write and take test
		char tmp[256];
		for(long i=0;;i++) {
			vector< CSmartTemplate<CObject> > bulk;
			//CMessage *key = NULL;
			CKeyValue *keyval = NULL;

			if(i>=0) {
				cout << "before write" << endl;
				cout << "==================================================" << endl;
				cout << mon << endl;
				system(mon);
				cout << "==================================================" << endl;
				cout << endl << endl;
			}
			
			for(int k=0;k<1000;k++) {
				CKeyValue kv;
				sprintf(tmp, "woorung-%d",getRandom());

				string haha = tmp;
				haha += msg.get();

				kv.set(tmp, (char *)haha.c_str());
				space.write(&kv);
			}

			if(i>=25) {
				cout << "after write" << endl;
				cout << "==================================================" << endl;
				cout << mon << endl;
				system(mon);
				cout << "==================================================" << endl;
				cout << endl << endl;
			}

			if(i>=50) {
				cout << "before take" << endl;
				cout << "==================================================" << endl;
				cout << mon << endl;
				system(mon);
				cout << "==================================================" << endl;

				cout << endl << endl;
				cout << "[write]current size = " << space.size() << endl;
				bulk = space.take(keyval, space.size(), bulk);
				cout << "[bulk take]current size = " << space.size() << endl;

				cout << "after take" << endl;
				cout << "==================================================" << endl;
				cout << mon << endl;
				system(mon);
				cout << "==================================================" << endl;

				i = -1;
				sleep(3);
			}
		}
	}

	return 1;
}
